package com.mkait.thief.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;


/**@desc  : 图片处理工具类
 * 功能：缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等
 *
 * @author: shirayner
 * @date  : 2017年10月17日 上午10:14:52
 */
public class ImgUtils {

    /**
     * 几种常见的图片格式
     */
    public static String IMAGE_TYPE_GIF = "gif";// 图形交换格式
    public static String IMAGE_TYPE_JPG = "jpg";// 联合照片专家组
    public static String IMAGE_TYPE_JPEG = "jpeg";// 联合照片专家组
    public static String IMAGE_TYPE_BMP = "bmp";// 英文Bitmap（位图）的简写，它是Windows操作系统中的标准图像文件格式
    public static String IMAGE_TYPE_PNG = "png";// 可移植网络图形
    public static String IMAGE_TYPE_PSD = "psd";// Photoshop的专用格式Photoshop




    /**
     * 图片根据通道转成黑白
     * @param originPath 原文件目录
     * @param outputPath 输出文件目录
     * @param channel 根据哪个通道转黑白 1：Red 2：Green 3：Blue
     * @throws IOException
     */
    public static void changeImageToNoneColor(String originPath, String outputPath, int channel) throws IOException {
        File file = new File(originPath);
        BufferedImage image = ImageIO.read(file);
        changeAllARGB(image,channel);//将传入的bufferedimage 只保留红色通道的信息
        ImageIO.write(image,"jpg",new File(outputPath));
    }
    /**
     *
     * @param image BufferedImaged对象
     * @return 一个Map Key是图像的像素行数，Value是图像的该行中每一点的ARGB值
     */
    public static Map<Integer, ArrayList> getAllARGB(BufferedImage image){
        Map<Integer, ArrayList> result = new HashMap<>();
        int width = image.getWidth();
        int height = image.getHeight();//height
        for(int i = 0; i < height; i++){
            ArrayList<int[]> list = new ArrayList();//用list记录每一行的像素
            for(int j = 0; j < width; j++){
                int[] transARGB = transARGB(image.getRGB(j, i),-1);
                list.add(transARGB);
            }
            result.put(i,list);
        }
        return result;
    }

    /**
     *
     * @param image
     * @return
     */
    public static void changeAllARGB(BufferedImage image, int channel){

        int width = image.getWidth();
        int height = image.getHeight();//height
        for(int i = 0; i < height; i++){
            ArrayList<int[]> list = new ArrayList();//用list记录每一行的像素
            for(int j = 0; j < width; j++){
                int[] transARGB = transARGB(image.getRGB(j, i),channel);//获取只显示指定通道图层
                //System.out.println("正在处理的像素点坐标 x:" + j + " y:" + i);
                image.setRGB(j,i,array2Integer(transARGB));
            }
        }
    }

    /**
     * int型rgb转换成数组格式 并保留指定的通道
     * @param rgb  int型的rgb值 通过BufferedImage的getRGB方法获取的
     * @param channel 通道标识 1:Red 2:Green 3:Blue other：保留所有通道
     * @return 返回的是int型数组，ARGB四个通道的值 [Alpha,Red,Green,Blue]
     */
    public static int[] transARGB(int rgb, int channel){
        String argb = Integer.toBinaryString(rgb);
        //分割及二进制转换
        Integer alpha = Integer.parseInt(argb.substring(0,8),2);
        Integer red = Integer.parseInt(argb.substring(8,16),2);
        Integer green = Integer.parseInt(argb.substring(16,24),2);
        Integer blue = Integer.parseInt(argb.substring(24,32),2);
        //定义数组
        int[] argbArr = {alpha,red,green,blue};
        //只保留某一个通道的信息  即把除了Alpha通道外的全部改成所选通道的值
        if (channel == 1){
            argbArr = new int[]{argbArr[0],argbArr[1],argbArr[1],argbArr[1]};
        }
        if (channel == 2){
            argbArr = new int[]{argbArr[0],argbArr[2],argbArr[2],argbArr[2]};
        }
        if (channel == 3){
            argbArr = new int[]{argbArr[0],argbArr[3],argbArr[3],argbArr[3]};
        }
        return argbArr;
    }

    /**
     * 获取图像的分辨率
     * @return width像素数 * height像素数
     */
    public static String getSize(BufferedImage image) {
        int height = image.getHeight();
        int width = image.getWidth();
        System.out.println("width = " + width);
        System.out.println("height = " + height);
        return width + " x " + height;
    }

    /**
     * 只用于此class的方法转换 把记录ARGB的数组转成int信息
     * @param arr
     * @return
     */
    public static int array2Integer(int[] arr){
        //System.out.println(Arrays.toString(arr));
        //利用Integer.toBinaryString转码时发现一个问题，只会从第一个1开始记录，例如0011100会被记为11100，而我需要的是8位代码
        String s1 = get8BitBinaryString(Integer.toBinaryString(arr[0]));
        String s2 = get8BitBinaryString(Integer.toBinaryString(arr[1]));
        String s3 = get8BitBinaryString(Integer.toBinaryString(arr[2]));
        String s4 = get8BitBinaryString(Integer.toBinaryString(arr[3]));
        String origin = s1 + s2 + s3 + s4;
        if(origin.startsWith("1")){
            //判断首位是否是1，如果是1，则按照补码计算
            String[] split = origin.split("");
            StringBuilder originCode = new StringBuilder("");
            for(int i = 0; i < split.length; i++){
                if(split[i].equals("1")){
                    originCode.append("0");
                }
                if(split[i].equals("0")){
                    originCode.append("1");
                }
            }
            //System.out.println(originCode);
            //循环结果 +1 即为原码
            int i = Integer.parseInt(originCode.toString(),2) + 1;
            System.out.println("-i = " + -i);
            return -i;
        }
        System.out.println(origin);
        return Integer.parseInt(origin, 2);
    }

    /**
     * 把参数转换为8位二进制代码
     * @param s
     * @return
     */
    public static String get8BitBinaryString (String s){
        if(s.length() == 8){
            return s;
        }else{
            int length = s.length();
            String zero = "";
            for (int i = 0; i < 8 - length; i++){/*通过循环判断前面要加几个零*/
                zero += "0";
            }
            return zero + s;
        }
    }



    /*******************************************************************************************************/
    /**
     * 缩放图像（按比例缩放）
     * @param srcImageFile 源图像文件地址
     * @param result 缩放后的图像地址
     * @param scale 缩放比例
     * @param flag 缩放选择:true 放大; false 缩小;
     */
    public final static void scale(String srcImageFile, String result,
                                   int scale, boolean flag) {
        try {
            BufferedImage src = ImageIO.read(new File(srcImageFile)); // 读入文件
            int width = src.getWidth(); // 得到源图宽
            int height = src.getHeight(); // 得到源图长
            if (flag) {// 放大
                width = width * scale;
                height = height * scale;
            } else {// 缩小
                width = width / scale;
                height = height / scale;
            }
            Image image = src.getScaledInstance(width, height,
                    Image.SCALE_DEFAULT);
            BufferedImage tag = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            ImageIO.write(tag, "JPEG", new File(result));// 输出到文件流
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 缩放图像（按高度和宽度缩放）
     * @param srcImageFile 源图像文件地址
     * @param result 缩放后的图像地址
     * @param height 缩放后的高度
     * @param width 缩放后的宽度
     * @param bb 比例不对时是否需要补白：true为补白; false为不补白;
     */
    public final static void scale2(String srcImageFile, String result, int height, int width, boolean bb) {
        try {
            double ratio = 0.0; // 缩放比例
            File f = new File(srcImageFile);
            BufferedImage bi = ImageIO.read(f);
            Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);
            // 计算比例
            if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
                if (bi.getHeight() > bi.getWidth()) {
                    ratio = (new Integer(height)).doubleValue()
                            / bi.getHeight();
                } else {
                    ratio = (new Integer(width)).doubleValue() / bi.getWidth();
                }
                AffineTransformOp op = new AffineTransformOp(AffineTransform
                        .getScaleInstance(ratio, ratio), null);
                itemp = op.filter(bi, null);
            }
            if (bb) {//补白
                BufferedImage image = new BufferedImage(width, height,
                        BufferedImage.TYPE_INT_RGB);
                Graphics2D g = image.createGraphics();
                g.setColor(Color.white);
                g.fillRect(0, 0, width, height);
                if (width == itemp.getWidth(null))
                    g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
                            itemp.getWidth(null), itemp.getHeight(null),
                            Color.white, null);
                else
                    g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
                            itemp.getWidth(null), itemp.getHeight(null),
                            Color.white, null);
                g.dispose();
                itemp = image;
            }
            ImageIO.write((BufferedImage) itemp, "JPEG", new File(result));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 图像切割(按指定起点坐标和宽高切割)
     * @param srcImageFile 源图像地址
     * @param result 切片后的图像地址
     * @param x 目标切片起点坐标X
     * @param y 目标切片起点坐标Y
     * @param width 目标切片宽度
     * @param height 目标切片高度
     */
    public final static void cut(String srcImageFile, String result,
                                 int x, int y, int width, int height) {
        try {
            // 读取源图像
            BufferedImage bi = ImageIO.read(new File(srcImageFile));
            int srcWidth = bi.getHeight(); // 源图宽度
            int srcHeight = bi.getWidth(); // 源图高度
            if (srcWidth > 0 && srcHeight > 0) {
                Image image = bi.getScaledInstance(srcWidth, srcHeight,
                        Image.SCALE_DEFAULT);
                // 四个参数分别为图像起点坐标和宽高
                // 即: CropImageFilter(int x,int y,int width,int height)
                ImageFilter cropFilter = new CropImageFilter(x, y, width, height);
                Image img = Toolkit.getDefaultToolkit().createImage(
                        new FilteredImageSource(image.getSource(),
                                cropFilter));
                BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics g = tag.getGraphics();
                g.drawImage(img, 0, 0, width, height, null); // 绘制切割后的图
                g.dispose();
                // 输出为文件
                ImageIO.write(tag, "JPEG", new File(result));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 图像切割（指定切片的行数和列数）
     * @param srcImageFile 源图像地址
     * @param descDir 切片目标文件夹
     * @param rows 目标切片行数。默认2，必须是范围 [1, 20] 之内
     * @param cols 目标切片列数。默认2，必须是范围 [1, 20] 之内
     */
    public final static void cut2(String srcImageFile, String descDir,
                                  int rows, int cols) {
        try {
            if(rows<=0||rows>20) rows = 2; // 切片行数
            if(cols<=0||cols>20) cols = 2; // 切片列数
            // 读取源图像
            BufferedImage bi = ImageIO.read(new File(srcImageFile));
            int srcWidth = bi.getHeight(); // 源图宽度
            int srcHeight = bi.getWidth(); // 源图高度
            if (srcWidth > 0 && srcHeight > 0) {
                Image img;
                ImageFilter cropFilter;
                Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
                int destWidth = srcWidth; // 每张切片的宽度
                int destHeight = srcHeight; // 每张切片的高度
                // 计算切片的宽度和高度
                if (srcWidth % cols == 0) {
                    destWidth = srcWidth / cols;
                } else {
                    destWidth = (int) Math.floor(srcWidth / cols) + 1;
                }
                if (srcHeight % rows == 0) {
                    destHeight = srcHeight / rows;
                } else {
                    destHeight = (int) Math.floor(srcWidth / rows) + 1;
                }
                // 循环建立切片
                // 改进的想法:是否可用多线程加快切割速度
                for (int i = 0; i < rows; i++) {
                    for (int j = 0; j < cols; j++) {
                        // 四个参数分别为图像起点坐标和宽高
                        // 即: CropImageFilter(int x,int y,int width,int height)
                        cropFilter = new CropImageFilter(j * destWidth, i * destHeight,
                                destWidth, destHeight);
                        img = Toolkit.getDefaultToolkit().createImage(
                                new FilteredImageSource(image.getSource(),
                                        cropFilter));
                        BufferedImage tag = new BufferedImage(destWidth,
                                destHeight, BufferedImage.TYPE_INT_RGB);
                        Graphics g = tag.getGraphics();
                        g.drawImage(img, 0, 0, null); // 绘制缩小后的图
                        g.dispose();
                        // 输出为文件
                        ImageIO.write(tag, "JPEG", new File(descDir
                                + "_r" + i + "_c" + j + ".jpg"));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 图像切割（指定切片的宽度和高度）
     * @param srcImageFile 源图像地址
     * @param descDir 切片目标文件夹
     * @param destWidth 目标切片宽度。默认200
     * @param destHeight 目标切片高度。默认150
     */
    public final static void cut3(String srcImageFile, String descDir,
                                  int destWidth, int destHeight) {
        try {
            if(destWidth<=0) destWidth = 200; // 切片宽度
            if(destHeight<=0) destHeight = 150; // 切片高度
            // 读取源图像
            BufferedImage bi = ImageIO.read(new File(srcImageFile));
            int srcWidth = bi.getHeight(); // 源图宽度
            int srcHeight = bi.getWidth(); // 源图高度
            if (srcWidth > destWidth && srcHeight > destHeight) {
                Image img;
                ImageFilter cropFilter;
                Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
                int cols = 0; // 切片横向数量
                int rows = 0; // 切片纵向数量
                // 计算切片的横向和纵向数量
                if (srcWidth % destWidth == 0) {
                    cols = srcWidth / destWidth;
                } else {
                    cols = (int) Math.floor(srcWidth / destWidth) + 1;
                }
                if (srcHeight % destHeight == 0) {
                    rows = srcHeight / destHeight;
                } else {
                    rows = (int) Math.floor(srcHeight / destHeight) + 1;
                }
                // 循环建立切片
                // 改进的想法:是否可用多线程加快切割速度
                for (int i = 0; i < rows; i++) {
                    for (int j = 0; j < cols; j++) {
                        // 四个参数分别为图像起点坐标和宽高
                        // 即: CropImageFilter(int x,int y,int width,int height)
                        cropFilter = new CropImageFilter(j * destWidth, i * destHeight,
                                destWidth, destHeight);
                        img = Toolkit.getDefaultToolkit().createImage(
                                new FilteredImageSource(image.getSource(),
                                        cropFilter));
                        BufferedImage tag = new BufferedImage(destWidth,
                                destHeight, BufferedImage.TYPE_INT_RGB);
                        Graphics g = tag.getGraphics();
                        g.drawImage(img, 0, 0, null); // 绘制缩小后的图
                        g.dispose();
                        // 输出为文件
                        ImageIO.write(tag, "JPEG", new File(descDir
                                + "_r" + i + "_c" + j + ".jpg"));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 图像类型转换：GIF->JPG、GIF->PNG、PNG->JPG、PNG->GIF(X)、BMP->PNG
     * @param srcImageFile 源图像地址
     * @param formatName 包含格式非正式名称的 String：如JPG、JPEG、GIF等
     * @param destImageFile 目标图像地址
     */
    public final static void convert(String srcImageFile, String formatName, String destImageFile) {
        try {
            File f = new File(srcImageFile);
            f.canRead();
            f.canWrite();
            BufferedImage src = ImageIO.read(f);
            ImageIO.write(src, formatName, new File(destImageFile));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 彩色转为黑白
     * @param srcImageFile 源图像地址
     * @param destImageFile 目标图像地址
     */
    public final static void gray(String srcImageFile, String destImageFile) {
        try {
            BufferedImage src = ImageIO.read(new File(srcImageFile));
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorConvertOp op = new ColorConvertOp(cs, null);
            src = op.filter(src, null);
            ImageIO.write(src, "JPEG", new File(destImageFile));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 给图片添加文字水印
     * @param pressText 水印文字
     * @param srcImageFile 源图像地址
     * @param destImageFile 目标图像地址
     * @param fontName 水印的字体名称
     * @param fontStyle 水印的字体样式
     * @param color 水印的字体颜色
     * @param fontSize 水印的字体大小
     * @param x 修正值
     * @param y 修正值
     * @param alpha 透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
     */
    public final static void pressText(String pressText,
                                       String srcImageFile, String destImageFile, String fontName,
                                       int fontStyle, Color color, int fontSize,int x,
                                       int y, float alpha) {
        try {
            File img = new File(srcImageFile);
            Image src = ImageIO.read(img);
            int width = src.getWidth(null);
            int height = src.getHeight(null);
            BufferedImage image = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.drawImage(src, 0, 0, width, height, null);
            g.setColor(color);
            g.setFont(new Font(fontName, fontStyle, fontSize));
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
                    alpha));
            // 在指定坐标绘制水印文字
            g.drawString(pressText, (width - (getLength(pressText) * fontSize))
                    / 2 + x, (height - fontSize) / 2 + y);
            g.dispose();
            ImageIO.write((BufferedImage) image, "JPEG", new File(destImageFile));// 输出到文件流
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 给图片添加文字水印
     * @param pressText 水印文字
     * @param srcImageFile 源图像地址
     * @param destImageFile 目标图像地址
     * @param fontName 字体名称
     * @param fontStyle 字体样式
     * @param color 字体颜色
     * @param fontSize 字体大小
     * @param x 修正值
     * @param y 修正值
     * @param alpha 透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
     */
    public final static void pressText2(String pressText, String srcImageFile,String destImageFile,
                                        String fontName, int fontStyle, Color color, int fontSize, int x,
                                        int y, float alpha) {
        try {
            File img = new File(srcImageFile);
            Image src = ImageIO.read(img);
            int width = src.getWidth(null);
            int height = src.getHeight(null);
            BufferedImage image = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.drawImage(src, 0, 0, width, height, null);
            g.setColor(color);
            g.setFont(new Font(fontName, fontStyle, fontSize));
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
                    alpha));
            // 在指定坐标绘制水印文字
            g.drawString(pressText, (width - (getLength(pressText) * fontSize))
                    / 2 + x, (height - fontSize) / 2 + y);
            g.dispose();
            ImageIO.write((BufferedImage) image, "JPEG", new File(destImageFile));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 给图片添加图片水印
     * @param pressImg 水印图片
     * @param srcImageFile 源图像地址
     * @param destImageFile 目标图像地址
     * @param x 修正值。 默认在中间
     * @param y 修正值。 默认在中间
     * @param alpha 透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
     */
    public final static void pressImage(String pressImg, String srcImageFile,String destImageFile,
                                        int x, int y, float alpha) {
        try {
            File img = new File(srcImageFile);
            Image src = ImageIO.read(img);
            int wideth = src.getWidth(null);
            int height = src.getHeight(null);
            BufferedImage image = new BufferedImage(wideth, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.drawImage(src, 0, 0, wideth, height, null);
            // 水印文件
            Image src_biao = ImageIO.read(new File(pressImg));
            int wideth_biao = src_biao.getWidth(null);
            int height_biao = src_biao.getHeight(null);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
                    alpha));
            g.drawImage(src_biao, (wideth - wideth_biao) / 2,
                    (height - height_biao) / 2, wideth_biao, height_biao, null);
            // 水印文件结束
            g.dispose();
            ImageIO.write((BufferedImage) image,  "JPEG", new File(destImageFile));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算text的长度（一个中文算两个字符）
     * @param text
     * @return
     */
    public final static int getLength(String text) {
        int length = 0;
        for (int i = 0; i < text.length(); i++) {
            if (new String(text.charAt(i) + "").getBytes().length > 1) {
                length += 2;
            } else {
                length += 1;
            }
        }
        return length / 2;
    }


    /**
     *
     */
    public static void blurImage(String inputFilePath, String outputFilePath) throws IOException {
        BufferedImage image = ImageIO.read(new File(inputFilePath));

        float[] matrix = new float[9];
        for (int i = 0; i < 9; i++) {
            matrix[i] = 1.0f / 9.0f;
        }
        Kernel kernel = new Kernel(3, 3, matrix);
        ConvolveOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
        BufferedImage blurredImage = op.filter(image, null);

        ImageIO.write(blurredImage, "jpg", new File(outputFilePath));
    }

    /**
     *
     * @param sfile
     *            需要去噪的图像
     * @param destDir
     *            去噪后的图像保存地址
     * @throws IOException
     */
    public static void cleanLinesInImage(File sfile, String destDir)  throws IOException{
        File destF = new File(destDir);
        if (!destF.exists())
        {
            destF.mkdirs();
        }

        BufferedImage bufferedImage = ImageIO.read(sfile);
        int h = bufferedImage.getHeight();
        int w = bufferedImage.getWidth();

        // 灰度化
        int[][] gray = new int[w][h];
        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                int argb = bufferedImage.getRGB(x, y);
                // 图像加亮（调整亮度识别率非常高）
                int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
                int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
                int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
                if (r >= 255)
                {
                    r = 255;
                }
                if (g >= 255)
                {
                    g = 255;
                }
                if (b >= 255)
                {
                    b = 255;
                }
                gray[x][y] = (int) Math
                        .pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2)
                                * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
            }
        }

        // 二值化
        int threshold = ostu(gray, w, h);
        BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                if (gray[x][y] > threshold)
                {
                    gray[x][y] |= 0x00FFFF;
                } else
                {
                    gray[x][y] &= 0xFF0000;
                }
                binaryBufferedImage.setRGB(x, y, gray[x][y]);
            }
        }

        //去除干扰线条
        for(int y = 1; y < h-1; y++){
            for(int x = 1; x < w-1; x++){
                boolean flag = false ;
                if(isBlack(binaryBufferedImage.getRGB(x, y))){
                    //左右均为空时，去掉此点
                    if(isWhite(binaryBufferedImage.getRGB(x-1, y)) && isWhite(binaryBufferedImage.getRGB(x+1, y))){
                        flag = true;
                    }
                    //上下均为空时，去掉此点
                    if(isWhite(binaryBufferedImage.getRGB(x, y+1)) && isWhite(binaryBufferedImage.getRGB(x, y-1))){
                        flag = true;
                    }
                    //斜上下为空时，去掉此点
                    if(isWhite(binaryBufferedImage.getRGB(x-1, y+1)) && isWhite(binaryBufferedImage.getRGB(x+1, y-1))){
                        flag = true;
                    }
                    if(isWhite(binaryBufferedImage.getRGB(x+1, y+1)) && isWhite(binaryBufferedImage.getRGB(x-1, y-1))){
                        flag = true;
                    }
                    if(flag){
                        binaryBufferedImage.setRGB(x,y,-1);
                    }
                }
            }
        }


        // 矩阵打印
        for (int y = 0; y < h; y++)
        {
            for (int x = 0; x < w; x++)
            {
                if (isBlack(binaryBufferedImage.getRGB(x, y)))
                {
                    System.out.print("*");
                } else
                {
                    System.out.print(" ");
                }
            }
            System.out.println();
        }

        ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile
                .getName()));
    }

    public static boolean isBlack(int colorInt)
    {
        Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() <= 300)
        {
            return true;
        }
        return false;
    }

    public static boolean isWhite(int colorInt)
    {
        Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() > 300)
        {
            return true;
        }
        return false;
    }

    public static int isBlackOrWhite(int colorInt)
    {
        if (getColorBright(colorInt) < 30 || getColorBright(colorInt) > 730)
        {
            return 1;
        }
        return 0;
    }

    public static int getColorBright(int colorInt)
    {
        Color color = new Color(colorInt);
        return color.getRed() + color.getGreen() + color.getBlue();
    }

    public static int ostu(int[][] gray, int w, int h)
    {
        int[] histData = new int[w * h];
        // Calculate histogram
        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                int red = 0xFF & gray[x][y];
                histData[red]++;
            }
        }

        // Total number of pixels
        int total = w * h;

        float sum = 0;
        for (int t = 0; t < 256; t++)
            sum += t * histData[t];

        float sumB = 0;
        int wB = 0;
        int wF = 0;

        float varMax = 0;
        int threshold = 0;

        for (int t = 0; t < 256; t++)
        {
            wB += histData[t]; // Weight Background
            if (wB == 0)
                continue;

            wF = total - wB; // Weight Foreground
            if (wF == 0)
                break;

            sumB += (float) (t * histData[t]);

            float mB = sumB / wB; // Mean Background
            float mF = (sum - sumB) / wF; // Mean Foreground

            // Calculate Between Class Variance
            float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);

            // Check if new maximum found
            if (varBetween > varMax)
            {
                varMax = varBetween;
                threshold = t;
            }
        }

        return threshold;
    }


//    /**
//     *
//     * @param sfile
//     *            需要去噪的图像
//     * @param destDir
//     *            去噪后的图像保存地址
//     * @throws IOException
//     */
//    public static void cleanLinesInImage(File sfile, String destDir)  throws IOException{
//        File destF = new File(destDir);
//        if (!destF.exists())
//        {
//            destF.mkdirs();
//        }
//
//        BufferedImage bufferedImage = ImageIO.read(sfile);
//        int h = bufferedImage.getHeight();
//        int w = bufferedImage.getWidth();
//
//        // 灰度化
//        int[][] gray = new int[w][h];
//        for (int x = 0; x < w; x++)
//        {
//            for (int y = 0; y < h; y++)
//            {
//                int argb = bufferedImage.getRGB(x, y);
//                // 图像加亮（调整亮度识别率非常高）
//                int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
//                int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
//                int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
//                if (r >= 255)
//                {
//                    r = 255;
//                }
//                if (g >= 255)
//                {
//                    g = 255;
//                }
//                if (b >= 255)
//                {
//                    b = 255;
//                }
//                gray[x][y] = (int) Math
//                        .pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2)
//                                * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
//            }
//        }
//
//        // 二值化
//        int threshold = ostu(gray, w, h);
//        BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
//        for (int x = 0; x < w; x++)
//        {
//            for (int y = 0; y < h; y++)
//            {
//                if (gray[x][y] > threshold)
//                {
//                    gray[x][y] |= 0x00FFFF;
//                } else
//                {
//                    gray[x][y] &= 0xFF0000;
//                }
//                binaryBufferedImage.setRGB(x, y, gray[x][y]);
//            }
//        }
//
//        //去除干扰线条
//        for(int y = 1; y < h-1; y++){
//            for(int x = 1; x < w-1; x++){
//                boolean flag = false ;
//                if(isBlack(binaryBufferedImage.getRGB(x, y))){
//                    //左右均为空时，去掉此点
//                    if(isWhite(binaryBufferedImage.getRGB(x-1, y)) && isWhite(binaryBufferedImage.getRGB(x+1, y))){
//                        flag = true;
//                    }
//                    //上下均为空时，去掉此点
//                    if(isWhite(binaryBufferedImage.getRGB(x, y+1)) && isWhite(binaryBufferedImage.getRGB(x, y-1))){
//                        flag = true;
//                    }
//                    //斜上下为空时，去掉此点
//                    if(isWhite(binaryBufferedImage.getRGB(x-1, y+1)) && isWhite(binaryBufferedImage.getRGB(x+1, y-1))){
//                        flag = true;
//                    }
//                    if(isWhite(binaryBufferedImage.getRGB(x+1, y+1)) && isWhite(binaryBufferedImage.getRGB(x-1, y-1))){
//                        flag = true;
//                    }
//                    if(flag){
//                        binaryBufferedImage.setRGB(x,y,-1);
//                    }
//                }
//            }
//        }
//
//
//        // 矩阵打印
//        for (int y = 0; y < h; y++)
//        {
//            for (int x = 0; x < w; x++)
//            {
//                if (isBlack(binaryBufferedImage.getRGB(x, y)))
//                {
//                    System.out.print("*");
//                } else
//                {
//                    System.out.print(" ");
//                }
//            }
//            System.out.println();
//        }
//
//        ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile
//                .getName()));
//    }
//
//    public static boolean isBlack(int colorInt)
//    {
//        Color color = new Color(colorInt);
//        if (color.getRed() + color.getGreen() + color.getBlue() <= 300)
//        {
//            return true;
//        }
//        return false;
//    }
//
//    public static boolean isWhite(int colorInt)
//    {
//        Color color = new Color(colorInt);
//        if (color.getRed() + color.getGreen() + color.getBlue() > 300)
//        {
//            return true;
//        }
//        return false;
//    }
//
//    public static int isBlackOrWhite(int colorInt)
//    {
//        if (getColorBright(colorInt) < 30 || getColorBright(colorInt) > 730)
//        {
//            return 1;
//        }
//        return 0;
//    }
//
//    public static int getColorBright(int colorInt)
//    {
//        Color color = new Color(colorInt);
//        return color.getRed() + color.getGreen() + color.getBlue();
//    }
//
//    public static int ostu(int[][] gray, int w, int h)
//    {
//        int[] histData = new int[w * h];
//        // Calculate histogram
//        for (int x = 0; x < w; x++)
//        {
//            for (int y = 0; y < h; y++)
//            {
//                int red = 0xFF & gray[x][y];
//                histData[red]++;
//            }
//        }
//
//        // Total number of pixels
//        int total = w * h;
//
//        float sum = 0;
//        for (int t = 0; t < 256; t++)
//            sum += t * histData[t];
//
//        float sumB = 0;
//        int wB = 0;
//        int wF = 0;
//
//        float varMax = 0;
//        int threshold = 0;
//
//        for (int t = 0; t < 256; t++)
//        {
//            wB += histData[t]; // Weight Background
//            if (wB == 0)
//                continue;
//
//            wF = total - wB; // Weight Foreground
//            if (wF == 0)
//                break;
//
//            sumB += (float) (t * histData[t]);
//
//            float mB = sumB / wB; // Mean Background
//            float mF = (sum - sumB) / wF; // Mean Foreground
//
//            // Calculate Between Class Variance
//            float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
//
//            // Check if new maximum found
//            if (varBetween > varMax)
//            {
//                varMax = varBetween;
//                threshold = t;
//            }
//        }
//
//        return threshold;
//    }
//

}